#include "noeud.hpp"

Noeud* initNoeud (char * nom, bool verbose)
{
    Noeud *n = (Noeud*) malloc(sizeof(Noeud));
    n->nom = nom;

    n->arc_inc_ext = NULL;
    n->capa_arc_ext = 0;
    n->nb_arc_ext = 0;

    n->arc_inc_int = NULL;
    n->capa_arc_int = 0;
    n->nb_arc_int = 0;

    return n;
}

void affichageNoeud (const Noeud *n)
{
    cout << n->nom << endl;
    if (n->nb_arc_ext == 0)
    {
        cout << "  pas d'arcs incidents exterieurs" << endl;
    } else {
        cout << "  arcs incidents exterieurs :" << endl;
        for (int i =0; i<n->nb_arc_ext; i++)
        {
            affichageArcExt(n->arc_inc_ext[i]);
        }
    }
    if (n->nb_arc_int == 0)
    {
        cout << "  pas d'arcs incidents interieurs" << endl;
    } else {
        cout << "  arcs incidents interieurs :" << endl;
        for (int i =0; i<n->nb_arc_int; i++)
        {
            affichageArcInt(n->arc_inc_int[i]);
        }
    }
}

void ajouteArcExt (Noeud *n, Arc *a, bool verbose)
{
    if (verbose)
        cout << "entrée dans ajouteArcExt" << endl;

    if(n->capa_arc_ext == n->nb_arc_ext)
    {
        if (verbose)
            cout << "\tLe tableau doit être agrandi" << endl;

        if (n->capa_arc_ext == 0)
        {
            n->capa_arc_ext = 1;
            n->arc_inc_ext = (Arc **) malloc(sizeof(Arc*)*n->capa_arc_ext);
        } else {
            n->capa_arc_ext *= 2;
            n->arc_inc_ext = (Arc **) realloc(n->arc_inc_ext, sizeof(Arc*)*n->capa_arc_ext);
        }
    }
    n->arc_inc_ext[n->nb_arc_ext] = a;
    n->nb_arc_ext++;

    if (verbose)
    {
        cout << "ajout de l'arc dans le noeud, affichage du  noeud : " << endl;
        affichageNoeud(n);
        cout << endl;
    }
}

void ajouteArcInt (Noeud *n, Arc *a, bool verbose)
{
    if (verbose)
        cout << "entrée dans ajouteArcInt" << endl;

    if(n->capa_arc_int == n->nb_arc_int)
    {
        if (verbose)
            cout << "Le tableau doit être agrandi" << endl;

        if (n->capa_arc_int == 0)
        {
            n->capa_arc_int = 1;
            n->arc_inc_int = (Arc **) malloc(sizeof(Arc*)*n->capa_arc_int);
        } else {
            n->capa_arc_int *= 2;
            n->arc_inc_int = (Arc **) realloc(n->arc_inc_int, sizeof(Arc*)*n->capa_arc_int);
        }
    }
    n->arc_inc_int[n->nb_arc_int] = a;
    n->nb_arc_int++;

    if (verbose)
    {
        cout << "ajout de l'arc dans le noeud, affichage du  noeud : " << endl;
        affichageNoeud(n);
        cout << endl;
    }
}


int decrocherArcExt(Noeud *n, Arc *a, bool verbose)
{
    int i = 0;
    while(n->arc_inc_ext[i] != a)
    {
        if (verbose)
        {
            cout << n->arc_inc_ext[i]->src->nom << endl;
            cout << "nombre d'arcs : " << n->nb_arc_ext << " / i : " << i << endl;
        }

        if(i == n->nb_arc_ext) // l'arc n'est pas dans le noeud
        {
            cout << "l'arc n'est pas dans le noeud" << endl;
            return 1;
        }
        i++;
    }
    n->arc_inc_ext[i] = NULL;
    if(i < (n->nb_arc_ext - 1)) // si l'élement supprimé n'était pas le dernier
    {
        n->arc_inc_ext[i] = n->arc_inc_ext[n->nb_arc_ext - 1];
        n->arc_inc_ext[n->nb_arc_ext - 1] = NULL;
    }
    if(n->nb_arc_ext < n->capa_arc_ext/2)
    {
        n->capa_arc_ext /= 2;
        n->arc_inc_ext = (Arc **) realloc(n->arc_inc_ext, sizeof(Arc*)*n->capa_arc_ext);
    }
    n->nb_arc_ext --;
    return 0;
}

int decrocherArcInt(Noeud *n, Arc *a, bool verbose)
{
    int i = 0;
    while(n->arc_inc_int[i] != a)
    {
        if (verbose)
        {
            cout << n->arc_inc_int[i]->src->nom << endl;
            cout << "nombre d'arcs : " << n->nb_arc_int << " / i : " << i << endl;
        }

        if(i == n->nb_arc_int) // l'arc n'est pas dans le noeud
        {
            cout << "l'arc n'est pas dans le noeud" << endl;
            return 1;
        }
        i++;
    }
    n->arc_inc_int[i] = NULL;
    if(i < (n->nb_arc_int - 1)) // si l'élement supprimé n'était pas le dernier
    {
        n->arc_inc_int[i] = n->arc_inc_int[n->nb_arc_int - 1];
        n->arc_inc_int[n->nb_arc_int - 1] = NULL;
    }
    if(n->nb_arc_int < n->capa_arc_int/2)
    {
        n->capa_arc_int /= 2;
        n->arc_inc_int = (Arc **) realloc(n->arc_inc_int, sizeof(Arc*)*n->capa_arc_int);
    }
    n->nb_arc_int --;
    return 0;
}

void testamentNoeud (Noeud *n)
{
    //free(n->nom);
    n->capa_arc_ext = 0;
    n->capa_arc_int = 0;
    n->nb_arc_ext = 0;
    n->nb_arc_int = 0;
    free(n->arc_inc_ext);
    free(n->arc_inc_int);
    free(n);
}
